﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using LED_Utils.MultitrackControl;

namespace CustomDataBindingControl
{
	public partial class TrackEditorControl : UserControl
	{
		public TrackEditorControl()
		{
			InitializeComponent();

            SetStyle(ControlStyles.Selectable, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            GdiHelper.SetDoubleBuffer(flowLayoutPanel1 , true);

            TrackHeight = 40;
            HeaderHeight = 35;
            InnerWidth = 10000;
            InitialScale = 200;
            timeLinePanel1.Width = InnerWidth;

            timeLinePanel1.MouseDown  += new MouseEventHandler(timeLinePanel1_MouseClick); 

		}

        int x = 0;
        void timeLinePanel1_MouseClick(object sender, MouseEventArgs e)
        {
            OnTimePanelClick(e);
            previousPage = CurrentPage;
            x = PointToClient(MousePosition).X;   
           // OnMouseClick(new MouseEventArgs(MouseButtons.Left, 1, MousePosition.X, MousePosition.Y, 0));
        }
        public int HeaderHeight {
            get { return timeLinePanel1.Height; }
            set { timeLinePanel1.Height = value; }
        }

		private object _dataSource;


		[AttributeProvider(typeof(IListSource))]
		[RefreshProperties(RefreshProperties.Repaint)]
		[DefaultValue(null)]
		[Category("Data")]
		public object DataSource
		{
			get { return _dataSource; }
			set
			{
				_dataSource = value;
				if (_dataSource != null && _dataSource is IBindingList )
				{
					((IBindingList)_dataSource).ListChanged += new ListChangedEventHandler(CustomTrackEditorControl_ListChanged); 
				}
				TryBindDataSource();

			}
		}

		// 
		/// Get/Set the DataMember
		/// 
		[Category("Data")]
		[Editor("System.Windows.Forms.Design.DataMemberListEditor, System.Design, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
		public string DataMember
		{
			get { return _dataMember; }
			set { _dataMember = value; }
		}

		/// 
		/// Private storage for the data member
		/// 
		private string    _dataMember;

		

		void CustomTrackEditorControl_ListChanged(object sender, ListChangedEventArgs e)
		{
			switch (e.ListChangedType)
			{
				case ListChangedType.ItemAdded:
                    AddTrackControlInternal(e.NewIndex);
                    break;
				case ListChangedType.ItemDeleted:
                    RemoveTrackControlInternal(e.NewIndex);
                    break;
				case ListChangedType.ItemMoved:
				case ListChangedType.Reset:
					RefreshView();
					break;
				case ListChangedType.PropertyDescriptorAdded:
					break;
				case ListChangedType.PropertyDescriptorChanged:
					break;
				case ListChangedType.PropertyDescriptorDeleted:
					break;
				case ListChangedType.ItemChanged:

					break;
				default:
					break;
			}
            
		}

        private void RemoveTrackControlInternal(int index)
        {
            //SuspendLayout();
            TrackViewControl toDelete = Tracks[index];
            flowLayoutPanel1.Controls.Remove(toDelete);

            //if (index < 1)
            //    return;
            //this.dataManager.Position = index - 1;

            //ResumeLayout();
        }

        private void AddTrackControlInternal(int index)
        {
            object item = InnerList[index];
            TrackViewControl ctrl = CreateControl(item);
            flowLayoutPanel1.Controls.Add(ctrl);
        }

		private void TryBindDataSource()
		{
			if (_dataSource == null)
				return;

			if (!(_dataSource is IEnumerable))
				return;

            dataManager = (CurrencyManager)this.BindingContext[_dataSource] ;
            dataManager.PositionChanged += new EventHandler(dataManager_PositionChanged);
			RefreshView();
		}

        void dataManager_PositionChanged(object sender, EventArgs e)
        {
            this.Tracks[dataManager.Position].Select(); 
        }

        private CurrencyManager dataManager;


        private IList InnerList
        {
            get
            {
                if (dataManager == null)
                    return null;
                return dataManager.List;
            }
        }

        public int InnerWidth { get; set; }

		private void RefreshView()
		{
            if (InnerList.Count < 1)
                return;

			SuspendLayout();
            foreach (var item in Tracks)
            {
                flowLayoutPanel1.Controls.Remove(item);  
            }
			//flowLayoutPanel1.Controls.Clear();
			foreach (var item in (IEnumerable)_dataSource)
			{
                TrackViewControl ctrl = CreateControl(item);
                flowLayoutPanel1.Controls.Add(ctrl);
			}
			ResumeLayout();
		}

        private TrackViewControl CreateControl(object item)
        {
            TrackViewControl ctrl = new TrackViewControl();
            GdiHelper.SetDoubleBuffer(ctrl,true);
            ctrl.Width = InnerWidth;
            ctrl.Height = TrackHeight;
            ctrl.Margin = new Padding(0);
            ctrl.Padding = new Padding(1,0,0,0);
            ctrl.Select(false);
            ctrl.Enter += new EventHandler(ctrl_Enter);
            ctrl.KeyDown += new KeyEventHandler(ctrl_KeyDown); 

            ctrl.SelectedFrameChanged += new EventHandler(ctrl_SelectedFrameChanged);
            //ctrl.StateCommon.ColorStyle = ComponentFactory.Krypton.Toolkit.PaletteColorStyle.HalfCut;
            //ctrl.StateCommon.Color1  = Color.Silver ;
            //ctrl.StateCommon.Color2 = Color.DimGray;
            //ctrl.StateCommon.ColorStyle = ComponentFactory.Krypton.Toolkit.PaletteColorStyle.Solid;
            //ctrl.StateCommon.Color1 = Color.Gray;

            //Binding binding1 = new Binding("BackColor", item, "Color", false, DataSourceUpdateMode.OnPropertyChanged);
            //ctrl.DataBindings.Add(binding1);
            //BindingSource bs = new BindingSource(_dataSource, DataMember);
            ctrl.DataSource = item.GetType().GetProperty(DataMember).GetValue(item, null);
            //ctrl.DataSource = item;
            return ctrl;
        }

        void ctrl_KeyDown(object sender, KeyEventArgs e)
        {
            //MessageBox.Show(e.KeyCode.ToString());
            //if (e.KeyCode == Keys.Up)
            //{
            //    if (this.dataManager.Position <= 0)
            //        return;
            //    SetCurrent(this.dataManager.Position - 1);
            //    //this.Tracks[dataManager.Position-1].Select(); 
            //}
            //else if (e.KeyCode == Keys.Down)
            //{
            //    if (this.dataManager.Position >= this.dataManager.Count - 1)
            //        return;
            //    SetCurrent(this.dataManager.Position + 1);
            //    //this.Tracks[dataManager.Position+1].Select(); 
            //}
        }

		void ctrl_SelectedFrameChanged(object sender, EventArgs e)
		{
            OnSelectedFrameChanged();
			//SelectedFrame = ((TrackViewControl)sender).SelectedFrame;
		}

		public event EventHandler SelectedFrameChanged;
		private void OnSelectedFrameChanged()
		{
			if (SelectedFrameChanged != null)
			{
				SelectedFrameChanged(this, EventArgs.Empty);
			}
		}

        private void SetCurrent(int index)
        {
            this.BindingContext[_dataSource].Position = index;
            this.FindForm().BindingContext[_dataSource].Position = index;


            TrackViewControl ctrl = Tracks[index];
            if (ctrl == null)
                return;

            //int index = Tracks.IndexOf(ctrl);

            foreach (TrackViewControl item in Tracks)
            {
                //item.Select(false);

                if (item.Equals(ctrl))
                    item.Select(true);
                else
                    item.Select(false);
            }   

        }

		void ctrl_Enter(object sender, EventArgs e)
		{
            TrackViewControl ctrl = sender as TrackViewControl;
            if (ctrl == null)
                return;

            int index = Tracks.IndexOf(ctrl);
            //this.BindingContext[_dataSource].Position = index;
            //this.FindForm().BindingContext[_dataSource].Position = index;




            //foreach (TrackViewControl item in Tracks)
            //{
            //    //item.Select(false);

            //    if (item.Equals(ctrl))
            //        item.Select(true);
            //    else
            //        item.Select(false);
            //}   
            SetCurrent(index);
		}

		public object SelectedTrack
		{
			get
			{
				if (BindingContext[_dataSource].Position < 0)
					return null;
				return BindingContext[_dataSource].Current ;
			}
		}
        public object _selectedFrame;
        public object SelectedFrame
		{
			get
			{
                if (SelectedTrack == null)
                    return null;

                TrackViewControl ctrl = Tracks[dataManager.Position];
                return ctrl.SelectedFrame;
                //foreach (TrackViewControl track in Tracks)
                //{
                //    if (track.DataSource.Equals(SelectedTrack))
                //    {
                //        return track.SelectedFrame;
                //    }
                //}
                //return null;
			}
            //set
            //{
            //    //if (_selectedFrame!=value)
            //    //{
            //        _selectedFrame = value;
            //        OnSelectedFrameChanged();
            //    //}
            //}
		}

        public int TrackHeight { get; set; }


        public int InitialScale
        {
            get;
            set;
        }

        private List<TrackViewControl > Tracks
        {

            get { return flowLayoutPanel1.Controls.OfType<TrackViewControl>().ToList() ; }
        }



        private static int _percents=100;
        public static int ScalePercents
        {
            get { return _percents; }
        }
        public void PerformScale(int percents)
        {
            if (percents <= 0)
                return;

            timeLinePanel1.InitialScale = InitialScale;
            _percents = percents;
            timeLinePanel1.PerformScale(percents); ;


            foreach (TrackViewControl item in Tracks)
            {
                item.InitialScale = InitialScale;
                item.PerformScale(percents);
            }
        }

        public event EventHandler MillisecondsChanged;
        protected virtual void OnMillisecondsChanged()
        {
            if (MillisecondsChanged != null)
            {
                MillisecondsChanged(this, EventArgs.Empty);
            }
        }
        

        private double _milliseconds;
        public double Milliseconds
        {
            get
            {
                return timeLinePanel1.Milliseconds;
            }
            set
            {
                if (timeLinePanel1.Milliseconds != value)
                {
                    timeLinePanel1.Milliseconds = value;
                }
            }
        }
        bool autoScrollRegistered = false;
        int previousPage = 0;

        public int CurrentPage { get { return (int)Math.Floor((double)(timeLinePanel1.CurrentXLocation / (double)Width)); } }

        private void timeLinePanel1_MillisecondsChanged(object sender, EventArgs e)
        {
            OnMillisecondsChanged();
            double delta = 10d;

            if (CurrentPage - previousPage == 1/* && !autoScrollRegistered*/)
            {
                PerformScroll(Width);
                //autoScrollRegistered = true;
            }
            else
            {
                //autoScrollRegistered = false;
            }
            previousPage = CurrentPage;
            Invalidate(); 
        }

        public event MouseEventHandler TimePanelClick;
        protected virtual void OnTimePanelClick(MouseEventArgs e)
        {
            if (TimePanelClick != null)
            {
                TimePanelClick(this, e);
            }
        }

        private static Pen black = Pens.Black;
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
           // Point p = this.poin
            //Point top = new Point(x, timeLinePanel1.Height);
            //Point bottom = new Point(x, Height);
            //e.Graphics.DrawLine(black, top, bottom); 
            //timeLinePanel1.cur
        }

        protected override void OnScroll(ScrollEventArgs se)
        {
            base.OnScroll(se);
            previousPage = CurrentPage;
            Invalidate(); 
        }

        public void PerformScroll(int offset)
        {
            Point p = flowLayoutPanel1.AutoScrollPosition;
            flowLayoutPanel1.AutoScrollPosition = new Point(Math.Abs(p.X) + offset, p.Y);
            //ShowInfo();


        }

        public void PerformScroll2(int offset)
        {
            Point p = flowLayoutPanel1.AutoScrollPosition;
            flowLayoutPanel1.AutoScrollPosition = new Point(offset, p.Y);
            //ShowInfo();


        }


        

        public void ShowEditor(object frame,FrameEditorForm2.State state  )
        {
            if (frame == null)
                return;
            foreach (TrackViewControl  track in Tracks)
            {
                foreach (FrameViewControl  item in track.Frames)
                {
                    if (item.DataSource.Equals(frame))
                    {
                        item.ShowFrameEditor(state);
                        return;
                    }
                }
            }
        }

        private void flowLayoutPanel1_Scroll(object sender, ScrollEventArgs e)
        {
            OnScroll(e);
        }
    }
}
